import {reactive, ref, toRaw} from "vue";
import type IPageResp from "@/type/IPageResp.ts";
import resetDefault from "@/util/reset-default.ts";
import type IPageReq from "@/type/IPageReq.ts";
import type ISysRoleReq from "./type/req/ISysRoleReq.ts";
import type ISysRoleResp from "./type/resp/ISysRoleResp.ts";
import sysRoleApi from "./api/SysRoleApi.ts";
import type SysRolePermissionResp from "@/view/role/type/resp/SysRolePermissionResp.ts";
import type SysRolePermissionReq from "@/view/role/type/req/SysRolePermissionReq.ts";

/**
 * 角色表的CRUD相关代码
 */
export const useSysRoleCrud = () => {

    /**
     * 分页数据
     */
    const pageModel = reactive<IPageReq>({
        pageNo: 1,
        pageSize: 10
    })

    /**
     * search表单数据
     */
    const searchModel = reactive<ISysRoleReq>({})

    /**
     * 表格数据
     */
    const tableModel = reactive<IPageResp<ISysRoleResp>>({
        current: 1,
        size: 10,
        pages: 0,
        total: 0,
        records: []
    })

    /**
     * 新增和编辑框数据
     */
    const dialogModel = reactive<ISysRoleReq>({})

    /**
     * 分页查询
     */
    let loading = ref<boolean>(false)

    const page = () => {
        loading.value = true
        sysRoleApi.page({...toRaw(searchModel), ...toRaw(pageModel)})
            .then(result => {
                tableModel.current = result.current
                tableModel.size = result.size
                tableModel.pages = result.pages
                tableModel.total = result.total
                tableModel.records = result.records
            })
            .catch(() => {
                //查询出错，就清空数据
                tableModel.records = []
            })
            .finally(() => {
                loading.value = false
            })
    }

    const reset = () => {
        resetDefault(searchModel)
        page()
    }

    const pageChange = (pageNo: number, pageSize: number) => {
        pageModel.pageNo = pageNo
        pageModel.pageSize = pageSize
        page()
    }

    /**
     * 新增和编辑的dialog
     */
    let dialogVisible = ref(false)
    const openDialog = (row: any) => {
        if (row) {
            Object.assign(dialogModel, row)
        }
        dialogVisible.value = true
    }

    const closeDialog = () => {
        resetDefault(dialogModel)
        dialogVisible.value = false
    }

    const addOrUpdate = async () => {
        await sysRoleApi.addOrUpdate(dialogModel)
        closeDialog()
        page()
    }

    /**
     * 删除
     */
    const deleteByIds = async (ids: string[]) => {
        await sysRoleApi.deleteById(ids)
        page()
    }

    /**
     * 角色授权
     */
    const drawerVisible = ref<boolean>(false)
    const currentRoleId = ref<string>("")
    const treeData = reactive<SysRolePermissionResp[]>([])
    const originalPermissionIds = new Set<string | undefined>()
    const rolePermissionUpdate = reactive<SysRolePermissionReq>({
        deletedPermissionIds: [],
        insertedPermissionIds: [],
        roleId: ""
    })

    const listRolePermissions = async (roleId: string) => {
        const tree: SysRolePermissionResp[] = await sysRoleApi.listRolePermissions(roleId)
        Object.assign(treeData, tree)

        //获取当前角色拥有的权限id
        originalPermissionIds.clear()
        const dfs = (nodes: SysRolePermissionResp[]) => {
            for (const node of nodes) {
                if (node.roleId === roleId) {
                    originalPermissionIds.add(node.id);
                }

                if (node.children?.length) {
                    dfs(node.children);
                }
            }
        }
        dfs(tree)
    }

    const openDrawer = async (roleId: string) => {

        //获取角色权限数据
        await listRolePermissions(roleId)

        //查询指定角色的权限信息
        currentRoleId.value = roleId
        drawerVisible.value = true

        rolePermissionUpdate.roleId = roleId
        rolePermissionUpdate.insertedPermissionIds = []
        rolePermissionUpdate.deletedPermissionIds = []


    }

    const closeDrawer = () => {
        currentRoleId.value = ""
        drawerVisible.value = false

        rolePermissionUpdate.roleId = ""
        rolePermissionUpdate.insertedPermissionIds = []
        rolePermissionUpdate.deletedPermissionIds = []
    }

    const checkedChange = (id: string, checked: boolean) => {
        const originallyGranted = originalPermissionIds.has(id);

        if (checked) {
            if (!originallyGranted) {
                // 本来没有，现在选中了 → 需要新增
                addIfNotExist(rolePermissionUpdate.insertedPermissionIds, id);
            }

            // 不管原本有没有，只要现在是选中的，就不能出现在 deleted 中
            removeIfExist(rolePermissionUpdate.deletedPermissionIds, id);
        } else {
            if (originallyGranted) {
                // 本来有，现在取消 → 需要删除
                addIfNotExist(rolePermissionUpdate.deletedPermissionIds, id);
            }

            // 不管原本有没有，只要现在是取消的，就不能出现在 inserted 中
            removeIfExist(rolePermissionUpdate.insertedPermissionIds, id);
        }
    }
    const addIfNotExist = (arr: string[], id: string) => {
        if (!arr.includes(id)) {
            arr.push(id);
        }
    }
    const removeIfExist = (arr: string[], id: string) => {
        const idx = arr.indexOf(id);
        if (idx !== -1) {
            arr.splice(idx, 1);
        }
    }

    const updateRolePermissions = async () => {
        if (rolePermissionUpdate.insertedPermissionIds.length === 0 && rolePermissionUpdate.deletedPermissionIds.length === 0) {
            return
        }
        await sysRoleApi.updateRolePermissions(rolePermissionUpdate)
        closeDrawer()
    }

    return {
        searchModel,
        tableModel,
        dialogModel,
        loading,
        dialogVisible,
        drawerVisible,
        treeData,
        currentRoleId,
        page,
        reset,
        pageChange,
        openDialog,
        closeDialog,
        addOrUpdate,
        deleteByIds,
        openDrawer,
        closeDrawer,
        checkedChange,
        updateRolePermissions
    }
}